package com.xjt.excel.controller;


import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.xjt.excel.entity.PubImpExcelJdLog;
import com.xjt.excel.entity.PubImpExcelModel;
import com.xjt.excel.entity.PubImpExcelModelcol;
import com.xjt.excel.service.IImpExcelService;
import com.xjt.excel.service.impl.*;
import com.xjt.excel.util.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.jdbc.UncategorizedSQLException;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileNotFoundException;
import java.time.LocalDateTime;
import java.util.*;

/**
 * <p>
 * 批量导入日志信息表（提供导入日志查询功能） 前端控制器
 * </p>
 *
 * @author xujiangtao
 * @since 2021-05-18
 */
@RestController
@RequestMapping("/pub-imp-excel-jd-log")
public class PubImpExcelJdLogController {

    Logger logger = LoggerFactory.getLogger(this.getClass());
    @Autowired
    public PubImpExcelModelServiceImpl pubImpExcelModelService;

    @Autowired
    public PubImpExcelModelcolServiceImpl pubImpExcelModelcolService;

    @Autowired
    public PubImpExcelJdLogServiceImpl pubImpExcelJdLogService;

    @Autowired
    public PubImpExcelValidLogServiceImpl pubImpExcelValidLogService;

    @Autowired
    public PubImpExcelValidRuleServiceImpl pubImpExcelValidRuleService;

    /**
     * 接收文件保存位置
     */
    @Value("${importExcelFile}")
    String importExcelFile="";


    /**
     *
     * @param file      上传的excel文件
     * @param menuId        配置表的对应id
     * @param response      响应体对象
     */
    @RequestMapping(value = "/uploads",method = RequestMethod.POST)
    @ResponseBody
    public void importExcel(@RequestParam("file") MultipartFile file, Long menuId, HttpServletResponse response) {
        Map<String, Object> message = new HashMap<>();
        if (file.isEmpty()){
            message.put("code", 400);
            message.put("msg", "文件为空");
            BaseControllerUtil.renderResult(response, message);
            return;
        }
        long startData = System.currentTimeMillis();
// 判断文件是否为空
        LocalDateTime startTime = LocalDateTime.now();
        String path = importExcelFile;
        ReadExcelUtil.setPubImpExcelValidLogServiceImpl(pubImpExcelValidLogService);
        ReadExcelUtil.setPubImpExcelValidRuleServiceImpl(pubImpExcelValidRuleService);
        String originalFilename = file.getOriginalFilename();
        String fileMD5String;
        try {
            fileMD5String = MD5File.getFileMD5String(FileUtil.multipartFileToFile(file));
            QueryWrapper<PubImpExcelJdLog> qw = new QueryWrapper<>();
            qw.eq("state", 1);
            qw.eq("jd_state", "从临时表插入数据到正式表完成");
            qw.eq("md5code", fileMD5String);
            PubImpExcelJdLog one = pubImpExcelJdLogService.getOne(qw);
            if (one!=null){
                message.put("code", 408);
                message.put("msg", "当前表已存在");
                BaseControllerUtil.renderResult(response, message);
                return;
            }
        } catch (Exception e) {
            e.printStackTrace();
            message.put("code", 416);
            message.put("msg", "表数据异常");
            BaseControllerUtil.renderResult(response, message);
            return;
        }
        if (!ReadExcelUtil.validateExcel(originalFilename)){            //判断是不是excel文件
            message.put("code", 403);
            message.put("msg", "不是excel文件");
            BaseControllerUtil.renderResult(response, message);
            return;
        }
        assert originalFilename != null;
        String[] split = originalFilename.split("\\.");
        String suffix = split[split.length-1];          //获取上传文件的后缀
        try {
            // 文件保存路径
            String filePath = path + "/" + UUID.randomUUID().toString().replace("-", "")+"."+suffix;
            QueryWrapper<PubImpExcelModel> qmodel = new QueryWrapper<>();
            qmodel.eq("menu_id", menuId);
            qmodel.eq("state", 1);
            List<PubImpExcelModel> excelModels = pubImpExcelModelService.list(qmodel);//模板表信息
            if (excelModels == null || excelModels.size()<1) {
                message.put("code", 501);
                message.put("msg", "未配置导出模板");
                BaseControllerUtil.renderResult(response, message);
                return;
            }
            for (int i = 0; i < excelModels.size(); i++) {
                QueryWrapper<PubImpExcelModelcol> modelcol = new QueryWrapper<>();
                modelcol.eq("state", 1);
                modelcol.eq("model_id", excelModels.get(i).getId());
                List<PubImpExcelModelcol> ModelcolList = pubImpExcelModelcolService.list(modelcol);     //字段列信息

                Map<Integer, String> res = ReadExcelUtil.readExcelhead(file,i);           //表头信息

                PubImpExcelJdLog pubImpExcelJdLog = new PubImpExcelJdLog();
                pubImpExcelJdLog.setState(1);
                pubImpExcelJdLog.setMenuId(menuId);
                pubImpExcelJdLog.setPcNum(FileUtils.getUUID());
                pubImpExcelJdLog.setJdState("上传中");
                pubImpExcelJdLog.setStartTime(startTime);
                pubImpExcelJdLog.setOperUid(0L);
                pubImpExcelJdLog.setSourceFileName(originalFilename);
                pubImpExcelJdLog.setSouceFilePath(filePath);
                pubImpExcelJdLog.setMd5code(fileMD5String);
                pubImpExcelJdLogService.saveOrUpdate(pubImpExcelJdLog);             //记录保存日志信息
                Long pubImpExcelJdLogId = pubImpExcelJdLog.getId();
                String tableName = "i"+excelModels.get(i).getId()+"_"+pubImpExcelJdLogId;         //临时表明

                pubImpExcelJdLog.setJdState("创建临时表");
                pubImpExcelJdLog.setTmpTableName(tableName);
                pubImpExcelJdLogService.saveOrUpdate(pubImpExcelJdLog);

                pubImpExcelModelService.createTable(tableName, ModelcolList);  //创建临时表

                if (!new File(filePath).exists()){          //保存目录如果不存在，则递归创建目录
                    if (new File(filePath).mkdirs()){
                        logger.info("父目录创建成功");
                    }
                }
                //将接受的文件保存
                if (i==0){
                    file.transferTo(new File(filePath));            //将接受的文件保存
                }
                pubImpExcelJdLog.setJdState("上传成功");
                pubImpExcelJdLogService.saveOrUpdate(pubImpExcelJdLog);

                message.put("filePath", filePath);
                pubImpExcelJdLog.setJdState("开始解析");
                pubImpExcelJdLogService.saveOrUpdate(pubImpExcelJdLog);
                Map<String, Object> excelInfos;
                try {
                    excelInfos = ReadExcelUtil.getExcelInfo(filePath, ModelcolList, pubImpExcelJdLogId,res,i);//获取的excel数据
                } catch (FileNotFoundException e){
                    e.printStackTrace();
                    message.put("code", 506);
                    message.put("msg", "找不到文件");
                    BaseControllerUtil.renderResult(response, message);
                    return;
                }catch (Exception e){
                    e.printStackTrace();
                    message.put("code", 504);
                    message.put("msg", "数据解析异常,excel数据不匹配");
                    BaseControllerUtil.renderResult(response, message);
                    return;
                }
                assert excelInfos != null;
                List<List<String>> excelInfo = (List<List<String>>) excelInfos.get("list");
                List<String> excelColumnList = new ArrayList<>();
                List<String> colCodeList = new ArrayList<>();
                for (PubImpExcelModelcol pubImpExcelModelcol : ModelcolList) {
                    String excelColumn = pubImpExcelModelcol.getExcelColumn();
                    String colCode = pubImpExcelModelcol.getColCode();
                    excelColumnList.add(excelColumn);
                    colCodeList.add(colCode);
                }
                assert excelInfo != null;
                pubImpExcelJdLog.setJdState("开始插入数据到临时表");
                pubImpExcelJdLogService.saveOrUpdate(pubImpExcelJdLog);
                try {
                    pubImpExcelModelService.saveData(tableName, excelInfo);
                }catch (UncategorizedSQLException e){
                    e.getSQLException();
                    message.put("code", 302);
                    message.put("msg", "必填项不能为空");
                    BaseControllerUtil.renderResult(response, message);
                    return;
                }
                pubImpExcelJdLog.setJdState("插入数据到临时表完成");
                pubImpExcelJdLogService.saveOrUpdate(pubImpExcelJdLog);
//                System.out.println(excelInfo);
//            System.out.println(integer);
                String serviceName = excelModels.get(i).getServiceName();
                pubImpExcelJdLog.setJdState("开始从临时表插入数据到正式表");
                pubImpExcelJdLogService.saveOrUpdate(pubImpExcelJdLog);

                IImpExcelService IImpExcelService = (IImpExcelService) SpringContextUtil.getBean(serviceName);
                Integer count = IImpExcelService.importExcelToDb(tableName, excelColumnList, colCodeList);
                pubImpExcelJdLog.setEndTime(LocalDateTime.now());
                pubImpExcelJdLog.setProblemnum(Integer.valueOf(excelInfos.get("fail").toString()));
                pubImpExcelJdLog.setJdState("从临时表插入数据到正式表完成");
                pubImpExcelJdLog.setTotalRow(count);
                pubImpExcelJdLogService.saveOrUpdate(pubImpExcelJdLog);         //保存日志
                long endData = System.currentTimeMillis();
                long expendTime = (endData - startData) / 1000;
                message.put("expendTime",expendTime/60+"m"+expendTime%60+"s");
                message.put("temTableName",tableName);
                message.put("status", "success");
                message.put("code", 200);
                message.put("successImportCount", count);
                BaseControllerUtil.renderResult(response, message);
            }

        } catch (Exception e) {
//                e.printStackTrace();
            message.put("status", "error");
        }
    }
}
